package munci.core;

import java.lang.reflect.Type;

public interface Word {
	
	/**
	 * Attribute object for immediate words
	 */
	public static final Object IMMEDIATE = new Object() {
		@Override public String toString() {
			return "Immediate";
		}
	};
	
	Class<?> returnType();
	
	Type genericReturnType();
	
	Class<?>[] parameterTypes();
	
	Object invoke(Object... args);
	
	public boolean hasAttribute(Object attribute);
	
	public interface V0 extends Word {
		void call();
	}
	
	public interface V1<P1> extends Word {
		void call(P1 p1);
	}
	
	public interface V2<P1, P2> extends Word {
		void call(P1 p1, P2 p2);
	}
	
	public interface V3<P1, P2, P3> extends Word {
		void call(P1 p1, P2 p2, P3 p3);
	}
	
	public interface V4<P1, P2, P3, P4> extends Word {
		void call(P1 p1, P2 p2, P3 p3, P4 p4);
	}
	
	public interface Returns<R> extends Word {
		Class<R> returnType();
		R invoke(Object... args);
	}
	
	public interface R0<R> extends Returns<R> {
		R call();
	}
	
	public interface R1<R, P1> extends Returns<R> {
		R call(P1 p1);
	}
	
	public interface R2<R, P1, P2> extends Returns<R> {
		R call(P1 p1, P2 p2);
	}
	
	public interface R3<R, P1, P2, P3> extends Returns<R> {
		R call(P1 p1, P2 p2, P3 p3);
	}
	
	public interface R4<R, P1, P2, P3, P4> extends Returns<R> {
		R call(P1 p1, P2 p2, P3 p3, P4 p4);
	}
}
